﻿// 2025/10/20: 首个版本

using System;
using System.Threading.Tasks;
using System.IO;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Avalonia.Controls;
using ASEva;
using ASEva.UIAvalonia;
using ASEva.Utility;

namespace CommonSource
{
    partial class SingleSessionPicker : DialogPanel
    {
        public SingleSessionPicker() // For designer
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
        }

        public SingleSessionPicker(object caller, SessionIdentifier session, String iconResourceName = null)
        {
            InitializeComponent();
            SetFixMode(720, 400, true);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
            Icon = ResourceLoader.Load(iconResourceName)?.ToAvaloniaWindowIcon();
            Title = language["title"];
            var model = new SingleSessionPickerViewModel(this, language, caller, session, optionsControl.DataContext as CommonPickOptionsControlViewModel);
            model.InitializeInfos();
            model.CloseRequest += delegate { Close(); };
            DataContext = model;
            optionsControl.WithEventFilter = true;
        }

        private LanguageSwitch language;
    }

    partial class SingleSessionPickerViewModel(Control view, LanguageSwitch language, object caller, SessionIdentifier session, CommonPickOptionsControlViewModel optionsModel) : ObservableObject
    {
        [ObservableProperty]
        private string sourceSessionDateTimeText = session.ToDateTime().ToString(language["date-time-format"]);

        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(OutputPathText))]
        [NotifyPropertyChangedFor(nameof(CanPick))]
        private string outputPath = null;

        public string OutputPathText => OutputPath ?? language["not-configured"];

        [RelayCommand]
        private async Task SelectOutputPath()
        {
            String selected = null;
            if (AgencyLocal.ClientSide)
            {
                await AgencyAsync.RunConsole(caller, "select-folder.consoleworkflow");
                selected = await AgencyAsync.GetGlobalVariable("Console.SelectFolderResult", null);
            }
            else
            {
                selected = await App.ShowSelectFolderDialog(view, language["dialog-title"]);
            }
            if (String.IsNullOrEmpty(selected)) return;

            OutputPath = selected;
        }

        private static String defaultPickID = "pick-" + DateTime.Now.ToString("yyyyMMddHHmmss");

        [ObservableProperty]
        private string pickID = defaultPickID;

        partial void OnPickIDChanged(string value)
        {
            if (String.IsNullOrEmpty(PickID)) PickID = defaultPickID;
        }

        private double sessionLength = 0;

        public async void InitializeInfos()
        {
            view.IsEnabled = false;

            if (AgencyLocal.ClientSide)
            {
                var length = await AgencyAsync.GetSessionLength(session);
                if (length == null)
                {
                    await delayShow(language["failed-load-info"]);
                    CloseRequest?.Invoke(this, EventArgs.Empty);
                    return;
                }
                sessionLength = length.Value;
            }
            else
            {
                var sessionPath = AgencyLocal.GetSessionPath(session);
                var meta = sessionPath == null ? null : SessionMeta.Load(sessionPath + System.IO.Path.DirectorySeparatorChar + "meta.xml");
                if (meta == null || meta.Length == null)
                {
                    await delayShow(language["failed-load-info"]);
                    CloseRequest?.Invoke(this, EventArgs.Empty);
                    return;
                }
                sessionLength = meta.Length.Value;
            }

            if (sessionLength <= 5)
            {
                await delayShow(language["short-session-length"]);
                CloseRequest?.Invoke(this, EventArgs.Empty);
                return;
            }

            PickFromMin = 0;
            PickFromMax = sessionLength - 5;
            PickFrom = 0;
            PickLengthMin = 5;
            PickLengthMax = sessionLength;
            PickLength = 5;

            view.IsEnabled = true;
        }

        private async Task delayShow(String msg)
        {
            await Task.Delay(100);
            await AgencyLocal.PopupError(msg);
        }

        [ObservableProperty]
        private double pickFrom;

        partial void OnPickFromChanged(double value)
        {
            PickLengthMax = sessionLength - value;
            PickLength = Math.Max(5, Math.Min(PickLength, PickLengthMax));
        }

        [ObservableProperty]
        private double pickFromMin;

        [ObservableProperty]
        private double pickFromMax;

        [ObservableProperty]
        private double pickLength;

        [ObservableProperty]
        private double pickLengthMin;

        [ObservableProperty]
        private double pickLengthMax;

        public bool CanPick => OutputPath != null;

        [RelayCommand]
        private async Task Pick()
        {
            String dataPath = null;
            if (AgencyLocal.ClientSide)
            {
                dataPath = await AgencyAsync.GetGlobalParameter("System.DataPath", null);
            }
            else
            {
                dataPath = AgencyLocal.GetDataPath();
            }

            var targetPath = OutputPath;
            if (dataPath != null && targetPath.IndexOf(dataPath + Path.DirectorySeparatorChar) >= 0)
            {
                await AgencyLocal.PopupError(language["folder-path-inside"]);
                return;
            }

            var pickConfig = new PickConfig();
            pickConfig.PickID = PickID.Length == 0 ? defaultPickID : PickID;
            pickConfig.Options = optionsModel.Result;

            var pick = new SingleSessionPick();
            pick.SourceSessionID = session;
            pick.SourceBeginTime = PickFrom;
            pick.SourcePickLength = PickLength;

            var dstSessionID = session.ToDateTime().AddSeconds((int)pick.SourceBeginTime);
            pick.DstSessionPath = targetPath + Path.DirectorySeparatorChar + dstSessionID.ToString("yyyyMMdd-HH-mm-ss");

            if (!AgencyLocal.ClientSide)
            {
                pick.SourceSessionPath = AgencyLocal.GetSessionPath(session);

                pick.SourceSubSessionPaths = new String[4];
                var subPaths = AgencyLocal.GetSubDataPaths();
                if (pick.SourceSessionPath.Length > dataPath.Length)
                {
                    var childPath = pick.SourceSessionPath.Substring(dataPath.Length + 1);
                    for (int i = 0; i < 4; i++)
                    {
                        if (i < subPaths.Length && subPaths[i] != null) pick.SourceSubSessionPaths[i] = subPaths[i] + Path.DirectorySeparatorChar + childPath;
                    }
                }
            }

            pickConfig.Picks.Add(pick);

            if ((await AgencyAsync.RunStandaloneTask(caller, "pick-session.system", pickConfig.ToXmlString())).Item1 == TaskResult.RunOK)
            {
                await AgencyLocal.PopupNotice(language["pick-ok"]);
                CloseRequest?.Invoke(this, EventArgs.Empty);
            }
        }

        public event EventHandler<EventArgs> CloseRequest;
    }
}